//
//  ASJGestureRecoginzer.m
//  ASJ001
//
//  Created by zephyrhan on 11/13/11.
//  Copyright (c) 2011 __MyCompanyName__. All rights reserved.
//

#import "ASJGestureRecoginzer.h"
#import "CGPointUtils.h"
#import <UIKit/UIGestureRecognizerSubclass.h>

#define kMinimumGestureLength 20
#define kMaximumVariance 8

#define kMinimumCheckMarkAngle    50
#define kMaximumCheckMarkAngle    135
#define kMinimumCheckMarkLength   10

#define POINT(X)	[[self.points objectAtIndex:X] CGPointValue]


@interface ASJGestureRecoginzer (privatemethod)

-(void)removeAll;

@end


@implementation ASJGestureRecoginzer

@synthesize hostLayer;
@synthesize showTrace;
@synthesize points, increasePointsArray;


-(id) init
{
	// always call "super" init
	// Apple recommends to re-assign "self" with the "super" return value
	if( (self=[super init])) {
		
		// create and initialize a Label
        self.isTouchEnabled = YES;
        numOfInflectionPoints = 0;
        numOfLargerThanPrevious = 0;
        tagOfSprite = 0;
        isInflection = NO;
        
        increasePointsX = [[NSMutableArray alloc]init];
        increasePointsY = [[NSMutableArray alloc]init];
        reducePointsY   = [[NSMutableArray alloc]init];
        deltaYTooLarge  = [[NSMutableArray alloc]init];
        angleInControl  = [[NSMutableArray alloc]init];
        angelInControl2 = [[NSMutableArray alloc]init];
        ArrayForInflectionpoint    = [[NSMutableArray alloc]init];
        pointlist = [[NSMutableArray alloc]init];
        
        
		// ask director the the window size
		CGSize size = [[CCDirector sharedDirector] winSize];
        
		// position the label on the center of the screen
		label.position =  ccp( size.width /2 , size.height/2 );
        
        [self schedule: @selector(tick:) interval:0.2f];
        
	}
	return self;
}




-(void) tick: (ccTime) dt
{
	//*********************************************
	//**
	//当滑动速度很慢时，不至于很快消失
	if ( [pointlist count] <30 ) {
		for (int i=0; i<1; i++) 
		{
			if ([pointlist count] >0)
			{
                //				pointlist.pop_front();
                [pointlist removeObjectAtIndex:0];
				pointcount--;
			}
			else {
				break;
			}
		}
		
		return;
	}
	
	for (int i=0; i<9 ; i++) 
	{
		if ([pointlist count] >0)
		{
            //            pointlist.pop_front();
            [pointlist removeObjectAtIndex:0];
            pointcount--;
		}
		else {
			break;
		}
	}
    
	//为了使线段不过长
	while (pointcount >200) {
        //		pointlist.pop_front();
        [pointlist removeObjectAtIndex:0];
		pointcount=[pointlist count];
	}
	//********************************************
}


float dotproduct (CGPoint v1, CGPoint v2)
{
	float dot = (v1.x * v2.x) + (v1.y * v2.y);
	float a = ABS(sqrt(v1.x * v1.x + v1.y * v1.y));
	float b = ABS(sqrt(v2.x * v2.x + v2.y * v2.y));
	dot /= (a * b);
	
	return dot;
}

// Return distance between two points
float distance (CGPoint p1, CGPoint p2)
{
	float dx = p2.x - p1.x;
	float dy = p2.y - p1.y;
	
	return sqrt(dx*dx + dy*dy);
}

// Calculate and return least bounding rectangle
- (CGRect) centeredRectangle
{
	float x = 0.0f;
	float y = 0.0f;
	for (NSValue *pt in self.points)
	{
		x += [pt CGPointValue].x;
		y += [pt CGPointValue].y;
	}
	
	// Calculate weighted center
	x /= self.points.count;
	y /= self.points.count;
	
	float minx = 9999.0f;
	float maxx = -9999.0f;
	float miny = 9999.0f;
	float maxy = -9999.0f;
	
	for (NSValue *pt in self.points)//查找所有点中的最大、最小值
	{
		minx = MIN(minx, [pt CGPointValue].x);
		miny = MIN(miny, [pt CGPointValue].y);
		maxx = MAX(maxx, [pt CGPointValue].x);
		maxy = MAX(maxy, [pt CGPointValue].y);
	}
	//CCLog(@"*******最小值=(%f,%f)", minx,miny);
	//CCLog(@"*******最大值=(%f,%f)", maxx,miny);    
	return CGRectMake(minx, miny, (maxx - minx), (maxy - miny));
}

// Return a point with respect to a given origin
CGPoint centerPoint(CGPoint pt, CGPoint origin)
{
	return CGPointMake(pt.x - origin.x, pt.y - origin.y);
}

-(void)checkM{
    if((numOfIncreasePointsY > 4) && numOfReducePointsY == 1 ){
        numOfCharacterM++;
        numOfIncreasePointsY =0 ;
    }
    if((numOfReducePointsY > 4) &&  numOfCharacterM==1 && numOfIncreasePointsY ==1 ){
        numOfCharacterM++;
        numOfReducePointsY = 0;
    }
    if((numOfIncreasePointsY > 4) &&  numOfCharacterM==2 && numOfReducePointsY ==1 ){
        numOfCharacterM++;
        numOfIncreasePointsY = 0;
    }   
}

-(void)checkChineseknot{
    
    if(numOfIncreasePointsYForknot > 5 && numOfReducePointsY ==1){
        numOfChineseknot++;
    }
    
    
}
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    
    [self removeAll];
    isInflection = NO;
    numOfReducePointsX = 0;
    numOfReducePointsY = 0;
    numOfIncreasePointsX = 0;
    numOfIncreasePointsY = 0;
    //测试中国结的点
    numOfIncreasePointsYForknot = 0;
    numOfIncreasePointsXForknot = 0;
    numOfReducePointsYForknot   = 0;
    numOfReducePointsXForknot   = 0;
    
    numOfLightsInflection = 0;
    numOfCharacterE  = 0;
    numOfCharacterM = 0;
    numOfCircleInflection =0;
    numOfChineseknot = 0;
    
    [label setString:@"begin"];
    UITouch *touch = [touches anyObject];
    startPoint= [self convertTouchToNodeSpace:touch];
    CGSize size = [[CCDirector sharedDirector] winSize];
    startPointSameX = ccp(startPoint.x , size.height);
    
	self.points = [NSMutableArray array];
	CGPoint pt = [touch locationInView:[touch view]];
	[self.points addObject:[NSValue valueWithCGPoint:pt]];
    
    lastPreviousPoint = startPoint;
    lastCurrentPoint  = startPoint;
    lineLengthSoFar   = 0.0f;
    
//    CCSprite *sprite = [CCSprite spriteWithBatchNode:spriteSheet rect:CGRectMake(0.0, 0.0, 16, 16)];
//    sprite.position = startPoint;
//    [spriteSheet addChild:sprite z:1 tag:tagOfSprite];
//    
//    [pointlist addObject:[NSValue valueWithCGPoint:startPoint]];
//    //CCLog(@"*******begin, point = %@", pointlist);
    
}

-(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    
    UITouch *touch = [touches anyObject];
    currentPosition = [self convertTouchToNodeSpace:touch];
    previousPoint = [touch previousLocationInView:[touch view]];
    previousPoint = [[CCDirector sharedDirector] convertToGL:previousPoint];
    
//    CCSprite *sprite = [CCSprite spriteWithBatchNode:spriteSheet rect:CGRectMake(0.0, 0.0, 16, 16)];
//    sprite.position = currentPosition;
//    tagOfSprite++;
//    [spriteSheet addChild:sprite z:1 tag:tagOfSprite];
    
    CGPoint pt = [touch locationInView:[touch view]];
	[self.points addObject:[NSValue valueWithCGPoint:pt]];  
    
    CGFloat deltaY = fabsf(startPoint.y - currentPosition.y);
    
    //与竖直方向的夹角
    CGFloat angle2 = angleBetweenLines(startPoint, 
                                       startPointSameX, 
                                       startPoint,
                                       currentPosition);
    
    lineLengthSoFar += distanceBetweenPoints(previousPoint, currentPosition);
    
    
    //水平增量
    if(currentPosition.x >= previousPoint.x){  //水平方向递增就设为1
        [increasePointsX addObject:@"1"];   //用于检测水平递增增量
        numOfIncreasePointsX++;
        numOfIncreasePointsXForknot++;
        //        //CCLog(@"********numofincreasePointsx = %d",numOfIncreasePointsX);
        //检测闪电的第一个拐点
        if(numOfLightsInflection==0 && numOfReducePointsX !=0 && numOfReducePointsY != 0 && numOfIncreasePointsX == 1){
            //            //CCLog(@"*************第一个拐点");
            [ArrayForInflectionpoint addObject:[NSValue valueWithCGPoint:previousPoint]];
            numOfReducePointsX = 0;
            numOfReducePointsY = 0;
            numOfLightsInflection++;
        }
        //检测E字母
        if((numOfLightsInflection == 2) && (numOfIncreasePointsX == 1) && (numOfReducePointsY > 1) ){
            //            //CCLog(@"***********此手势是E字幕");
            numOfCharacterE++;
            [ArrayForInflectionpoint addObject:[NSValue valueWithCGPoint:previousPoint]];
        }
        
        [self checkM];
        //检测M拐点（从右到左）
        //        if(numOfIncreasePointsY>4 &&)
        
        
        
    }
    else{
        [increasePointsX addObject:@"0"];
        numOfReducePointsX++;  
        numOfReducePointsXForknot++;
        //            //CCLog(@"********numofincreasePointsx = %d",numOfIncreasePointsX);
        //检测闪电的第二个拐点
        if(numOfLightsInflection==1 && numOfIncreasePointsX > 1 && numOfReducePointsX == 1){
            numOfLightsInflection++;
            [ArrayForInflectionpoint addObject:[NSValue valueWithCGPoint:previousPoint]];
            numOfReducePointsY = 0;
            numOfIncreasePointsY =0;
            numOfIncreasePointsX = 0;
            
        }
        //闪电拐点数加一
        //        if( (numOfLightsInflection==1) && numOfReducePointsX !=0 && numOfReducePointsY!=0 && numOfIncreasePointsY==0){
        //             numOfLightsInflection++;
        //            //CCLog(@"＊＊＊＊＊＊＊检测到第二个拐点，确认是闪电");
        //        }
        //检测M拐点（从右到左）
        [self checkM];
        //检测中国结第一个拐点
        if(numOfChineseknot==0 && numOfIncreasePointsXForknot!=0 && numOfReducePointsXForknot==1){
            //CCLog(@"********中国结拐点一");
            numOfChineseknot++;
            numOfReducePointsYForknot = 0;
        }
    }
    
    
    if(deltaY > 40){
        [deltaYTooLarge addObject:@"1"];
    }   
    
    //纵向增量
    if(currentPosition.y >= previousPoint.y){
        [increasePointsY addObject:@"1"];
        numOfIncreasePointsY++;
        numOfIncreasePointsYForknot++;    
    }
    else{
        [increasePointsY addObject:@"0"];
        [reducePointsY addObject:@"1"];
        numOfReducePointsY++;
        numOfReducePointsYForknot++;
        //        //检测中国结
        //        if(numOfIncreasePointsYForknot > 5 && numOfReducePointsYForknot ==1){
        //            numOfChineseknot++;
        //        }
        //检测中国结第二个拐点
        if(numOfChineseknot==1 && numOfReducePointsXForknot!=0 && numOfReducePointsYForknot==1 ){
            //CCLog(@"*******中国结拐点二");
            numOfChineseknot++;
            numOfIncreasePointsYForknot = 0;
            numOfIncreasePointsXForknot = 0;
        }
        
    }
    
    if(angle2  >=50){
        [angleInControl addObject:@"1"];
    }
    if(angle2 <= 130 ){
        [angelInControl2 addObject:@"1"];
    }
    
    lastPreviousPoint = previousPoint;
    lastCurrentPoint = currentPosition;
    
    
    //轨迹
	float distance = ccpDistance(currentPosition, previousPoint);
	if ( distance > 1 )
	{
		int d = (int)distance;
		for (int i = 0; i < d; i=i+1)
		{
			float difx = currentPosition.x - previousPoint.x;
			float dify = currentPosition.y - previousPoint.y;
			float delta = (float)i / distance;
			CGPoint p;
			p.x = previousPoint.x + (difx * delta);
			p.y = previousPoint.y + (dify * delta); 
			
            //			pointlist.push_back(p);
            [pointlist addObject:[NSValue valueWithCGPoint:p]];
		}
	}
    pointcount = [pointlist count];
    
    
}

-(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    
    ASJGestureType regType = 0;
    
    int distanceOfStartToEnd = distanceBetweenPoints(startPoint, currentPosition);
    
    //圆形的检测
    if (!self.points) return;
	if (self.points.count < 3) 
    {
        //CCLog(@"**************小于3");
        return;       
    }
	CGRect tcircle;
    //起始点距离<120
	if ( distanceOfStartToEnd < 120)
		tcircle = [self centeredRectangle]; 
	//弧度控制在45之内
	CGPoint center = CGPointMake(CGRectGetMidX(tcircle), CGRectGetMidY(tcircle));
	float distance = ABS(acos(dotproduct(centerPoint(POINT(0), center), centerPoint(POINT(1), center))));
	for (int i = 1; i < (self.points.count - 1); i++)
		distance += ABS(acos(dotproduct(centerPoint(POINT(i), center), centerPoint(POINT(i+1), center))));
	if ((ABS(distance - 2 * M_PI) < (M_PI / 4.0f))) 
    {
//        [label setString:@"圆形"];
        regType = ASJGESTYPE_R;
    }//圆形检测完
    
    //水平检测
    BOOL ifIncrease = ![increasePointsX containsObject:@"0"];
    BOOL ifReduce   = ![increasePointsX containsObject:@"1"];
    int num = [deltaYTooLarge count];
    int num2 = [increasePointsX count];
    BOOL ifdeltaYTooLarge = (num < 3);
    if( ifdeltaYTooLarge && num2!=0){
        if(ifReduce || ifIncrease)
//            [label setString:@"水平"];
        regType = ASJGESTYPE_H;
    }
    
    //竖直检测
    BOOL ifIncrease2 = ![increasePointsY containsObject:@"0"];
    BOOL ifReduce2   = ![increasePointsY containsObject:@"1"];
    int numOfAngleTooLarge = [angleInControl count];
    int numOfAngleTooLarge2 = [angelInControl2 count];
    int temp2 = [increasePointsY count];
    int temp3 = [reducePointsY count];
    //CCLog(@"temp2 = %d",temp2);
    //CCLog(@"temp3  =%d",temp3);
    if(ifIncrease2 &&(numOfAngleTooLarge < 2 ) &&  (temp2!=0)){
//        [label setString: @"垂直"];
        regType = ASJGESTYPE_V;
    }
    if(ifReduce2 && (numOfAngleTooLarge2 < 2 ) &&  (temp3!=0)){
//        [label setString:@"垂直"];
        regType = ASJGESTYPE_V;
    }
    
    
    
    int startToEndY =  currentPosition.y - startPoint.y;
    //CCLog(@" **********startToEndY = %d", startToEndY);
    //CCLog(@"*****guaidian = %@",ArrayForInflectionpoint);
    int distanceOfThirdToEnd = 0;
    if([ArrayForInflectionpoint count]==3){
        CGPoint thirdPoint = [[ArrayForInflectionpoint objectAtIndex:2] CGPointValue];
        distanceOfThirdToEnd = distanceBetweenPoints(thirdPoint, currentPosition);
    }
    //闪电检测
    //CCLog(@"**********lightsinflection =%d",numOfLightsInflection);
    //CCLog(@"**********distaceofstartToend = %d", distanceOfStartToEnd);
    //CCLog(@"**********startToEndY =%d", startToEndY);
    //CCLog(@"***********distanceofthirdToend = %d",distanceOfThirdToEnd);
    if( numOfLightsInflection ==2 && distanceOfStartToEnd > 50 && startToEndY < -50 && distanceOfThirdToEnd<20){//numOfCharacterE== 0 &&
        //[label setString: @"闪电"];
        regType = ASJGESTYPE_T;
    }
    //字母E检测
    if(numOfCharacterE ==1 && numOfLightsInflection ==2 && distanceOfThirdToEnd>30){
//        [label setString:@"字母E"];
        regType = ASJGESTYPE_E;
    }
    //M检测
    if( numOfCharacterM == 3){
//        [label setString:@"字母M"];
        regType = ASJGESTYPE_M;
    }
    //中国结检测
    //    float startToEndX =fabs(currentPosition.x - startPoint.x);
    //    //CCLog(@"******knottttttt= %d", numOfChineseknot);
    //    //CCLog(@"********numofreduceY = %d", numOfReducePointsYForknot);
    //    //CCLog(@"*****startToend distace=%d", distanceOfStartToEnd);
    //    //CCLog(@"******distance2 = %f", distance2);
    //    //CCLog(@"********numofreducepointsX=%d", numOfReducePointsX);
    //    if(numOfChineseknot==1 && startToEndX > 50 && numOfReducePointsX!=0){
    //        [label setString:@"中国结"];
    //    }
    //CCLog(@"***********numofchineseknot = %d",numOfChineseknot);
    if(numOfChineseknot==2 && currentPosition.y < previousPoint.y && numOfIncreasePointsXForknot==0){
//        [label setString:@"中国结"];
        regType = ASJGESTYPE_A;
    }
    numOfInflectionPoints = 0;
    numOfSmallerThanPrevious = 0;
    numOfLargerThanPrevious =0;
    numOfCharacterE = 0;
    numOfLightsInflection = 0;
    numOfReducePointsY = 0;
    //    startToEndX = 0;
    
    [increasePointsX removeAllObjects];
    [deltaYTooLarge  removeAllObjects];
    [increasePointsY removeAllObjects];
    [reducePointsY   removeAllObjects];
    [angleInControl  removeAllObjects];
    [angelInControl2 removeAllObjects]; //竖直检测
    [ArrayForInflectionpoint removeAllObjects];
    //轨迹

    if (regType != 0) {
        [pointlist performSelector:@selector(removeAllObjects) withObject:nil afterDelay:2.0];
        
        [[NSNotificationCenter defaultCenter] postNotificationName:GESTURE_RECOGNIZED object:[NSNumber numberWithInt:regType]];
    } else {
        [pointlist removeAllObjects];
    }
}


-(void)removeAll{
    int childrenOfspriteSheet = [[spriteSheet children] count];
    //    //CCLog(@"*****count = %d", childrenOfspriteSheet);
    
    if(childrenOfspriteSheet !=0){
        for(int i = 0; i <= tagOfSprite; i++){
            [spriteSheet removeChildByTag:i cleanup:YES];
        }
        tagOfSprite = 0;
    }
    
    
    
}


//测试从顶部开始画点
-(void) draw
{
    //	//CCLog(@"************draw");
    //	glClearColor(0.0,0,255,255);
	linewidth=15.0f;
	linewidthinc=0.10f;
	//float linewidth2= 0.30f;
	
    //	glEnable(GL_LINE_SMOOTH);
	float pointdrawcount = 1;
	int pointlistsize = [pointlist count];
    //	//CCLog(@"******size = %d", pointlistsize);
    if (pointlistsize > 0){
        CGPoint pointper = CGPointZero;
        CGPoint b = [[pointlist objectAtIndex:(pointlistsize - 1)] CGPointValue];
        CGPoint point_begin = [[pointlist objectAtIndex:0] CGPointValue];
        //        //CCLog(@"***********b = (%f, %f)", pointper.x, pointper.y);
        //        //CCLog(@"***********point_begin = (%f,%f)", point_begin.x, point_begin.y);
        for (; (b.x != point_begin.x) && (b.y != point_begin.y);) {
            pointdrawcount++;
            linewidth =linewidth- linewidth*2/(pointlistsize);
            //白色
            glColor4ub(231,179,37, 0);
            if (pointper.x > 1 && pointper.y > 1 ) 
            {
                //使用点，发现效果更好一点
                glPointSize(linewidth);
                ccDrawPoint(b);			
            }
            pointper = b;
            pointlistsize = pointlistsize - 1;
            
            //NSLog(@"pointlistsize:%d", pointlistsize);
            b = [[pointlist objectAtIndex:pointlistsize] CGPointValue];
        }
    }
}



// on "dealloc" you need to release all your retained objects
- (void) dealloc
{
	// in case you have something to dealloc, do it in this method
	// in this particular example nothing needs to be released.
	// cocos2d will automatically release all the children (Label)
    //	[spriteSheet release];
    
    
	// don't forget to call "super dealloc"
	[super dealloc];
}

@end
